'--------------------------------------------------------------------------------------
'Copyright: (c) 2010 Bentley Systems, Incorporated.
'--------------------------------------------------------------------------------------
'
'  This file is part of structural-gc.
'
'  structural-gc is free software: you can redistribute it and/or modify
'  it under the terms of the GNU General Public License as published by
'  the Free Software Foundation, either version 2 of the License, or
'  (at your option) any later version.
'
'  structural-gc is distributed in the hope that it will be useful,
'  but WITHOUT ANY WARRANTY; without even the implied warranty of
'  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'  GNU General Public License for more details.
'
'  You should have received a copy of the GNU General Public License
'  along with structural-gc.  If not, see <http://www.gnu.org/licenses/>
'--------------------------------------------------------------------------------------

Option Strict
Option Explicit

Imports System
Imports System.Collections
Imports System.Collections.Specialized
Imports System.Diagnostics
Imports Bentley.Interop.MicroStationDGN
Imports Bentley.GenerativeComponents.MicroStation
Imports Bentley.GenerativeComponents
Imports Bentley.GenerativeComponents.GCScript.Namescopes
Imports Bentley.GenerativeComponents.GeneralPurpose
Imports Bentley.GenerativeComponents.GCScript
Imports Bentley.Interop.TFCom
Imports Bentley.Interop.STFCom
Imports System.Windows.Forms
Imports Bentley.Geometry
Imports Bentley.GenerativeComponents.Structural.VB.Forms

Public Enum PlacementPointEnum
    This = 0
    That = 1
    SomethingElse = 7
End Enum

Namespace Bentley.GenerativeComponents.Features


    <GCNamespace("User")> _
    Public Class StructFormVB
        Inherits Feature

        Private Shared s_sectionPickerForm As SectionPickerForm
        Private Shared s_placementPointForm As PlacementPointForm
        Private Shared s_placeStructuralForm As PlaceStructuralForm


        Protected Sub OnConstituentElementAddedToDictionary_2(ByVal elem As Element) 'Overrides
            Dim tfElementMember As TFElement
            Dim tfElementList As New TFElementList
            Dim tfType As Integer
            Dim dID As DLong

            Dim comElement As Element = GetElement()


            tfElementList.InitFromElement(comElement)
            tfElementMember = DirectCast(tfElementList, TFElement)
            tfType = tfElementMember.GetApplicationType
            dID = tfElementMember.GetID()
            If dID.Low > 0 Or dID.High > 0 Then
                If tfType = TFdElementType.tfdElementTypeFormFreeStructural Then
                    Dim lnrMemberList As New STFLinearMemberList
                    lnrMemberList.InitFromDescr(comElement, True)
                    Dim lnrMember As STFLinearMember = lnrMemberList.AsSTFLinearMember
                    lnrMember.Save(True)
                End If
            End If
        End Sub

        Public Shared Function SectionPickerExpressionBuilder(ByRef expressionSourceCode As String) As Boolean
            If s_sectionPickerForm Is Nothing Then
                s_sectionPickerForm = New SectionPickerForm
            End If

            s_sectionPickerForm.ExpressionText = expressionSourceCode
            Dim dr As DialogResult = s_sectionPickerForm.ShowDialog()
            If dr <> DialogResult.OK Then Return False
            expressionSourceCode = s_sectionPickerForm.ExpressionText
            Return True
        End Function

        Public Shared Function PlacementPointExpressionBuilder(ByRef expressionSourceCode As String) As Boolean
            If s_placementPointForm Is Nothing Then
                s_placementPointForm = New PlacementPointForm
            End If

            Dim dr As DialogResult = s_placementPointForm.ShowDialog()
            If dr <> DialogResult.OK Then Return False
            expressionSourceCode = "s_placementPointForm.ExpressionText"
            Return True
        End Function

        Public Shared Function PlaceStructuralExpressionBuilder(ByRef expressionSourceCode As String) As Boolean
            If s_placeStructuralForm Is Nothing Then
                s_placeStructuralForm = New PlaceStructuralForm
            End If
            s_placeStructuralForm.ExpressionText = expressionSourceCode

            Dim dr As DialogResult = s_placeStructuralForm.ShowDialog()
            If dr <> DialogResult.OK Then Return False
            expressionSourceCode = s_placeStructuralForm.ExpressionText
            Return True
        End Function

        '<Update()> _
        'Public Function ByTwoPoints(ByVal updateContext As FeatureUpdateContext, _
        '                   <Replicatable(), ParentModel()> ByVal StartPoint As IPoint, _
        '                   <Replicatable()> ByVal EndPoint As IPoint) As Boolean

        '    'DeleteAllSubFeatures(updateContext)
        '    'DeleteElement(updateContext)

        '    Dim com_startPoint As Point3d = DgnTools.ToPoint3d(StartPoint.DPoint3d)
        '    Dim com_endPoint As Point3d = DgnTools.ToPoint3d(EndPoint.DPoint3d)

        '    Dim comElement As Element = MSApp.CreateLineElement2(TemplateElement, com_startPoint, com_endPoint)
        '    SetElement(comElement)

        '    Return True
        'End Function

        '        <Bentley.GenerativeComponents.Update(), Bentley.GenerativeComponents.Clone()> _
        <Update()> _
        Public Function ByPoints(ByVal updateContext As FeatureUpdateContext, _
                                   <Replicatable(), ParentModel()> ByVal StartPoint As IPoint, _
                                   <Replicatable()> ByVal EndPoint As IPoint, _
                                   <SpecializedExpressionBuilder("PlaceStructuralExpressionBuilder")> ByVal StructuralExpressionBuilderData As String, _
                                   <Out()> ByRef Length As Double) As Boolean

            'DeleteAllSubFeatures(updateContext)

            'If updateContext.InDynamics Then
            '    '    Length = comElement.AsLineElement().Length
            '    Return False
            'End If

            'DeleteElement(updateContext)

            Dim rotation As Double
            Length = 0.0
            If Not StartPoint Is Nothing And Not EndPoint Is Nothing Then

                Dim com_startPoint As Point3d = DgnTools.ToPoint3d(StartPoint.DPoint3d)
                Dim com_endPoint As Point3d = DgnTools.ToPoint3d(EndPoint.DPoint3d)

                'Else
                Dim sectionName As String = ""
                Dim familyName As String = ""
                Dim partName As String = ""
                Dim mark As String = ""

                Dim pos As Integer = StructuralExpressionBuilderData.IndexOf(":", 0)
                Dim pos2 As Integer
                pos2 = 0
                If pos > 0 Then
                    familyName = StructuralExpressionBuilderData.Substring(0, pos)
                    pos2 = pos + pos2
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    partName = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    sectionName = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    Dim rotationStr As String
                    rotationStr = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    rotation = Val(rotationStr)
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If
                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                Dim placementPoint As Integer
                If pos > 0 Then
                    Dim placementPointStr As String
                    Dim dPlacementPoint As Double
                    placementPointStr = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    dPlacementPoint = Val(placementPointStr)
                    placementPoint = CInt(dPlacementPoint)
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    mark = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                Dim member As STFLinearMember
                Dim section As STFSection
                Dim material As STFMaterial
                Dim memberList As STFLinearMemberList
                Dim sectionList As STFSectionList
                Dim materialList As STFMaterialList

                memberList = New STFLinearMemberList
                sectionList = New STFSectionList
                materialList = New STFMaterialList

                member = DirectCast(memberList, STFLinearMember)
                section = DirectCast(sectionList, STFSection)
                material = DirectCast(materialList, STFMaterial)

                Dim options As String = String.Empty

                ' --------------------------------------------
                '    material
                ' --------------------------------------------
                material.SetName("Steel", options)
                material.SetGrade("A36", options)
                member.SetRotation(rotation)
                member.SetMark(mark)

                ' --------------------------------------------
                '    section
                ' --------------------------------------------

                '                    Dim pos As Integer = SectionTableAndName.IndexOf(":")
                '                    If pos < 0 Then pos = SectionTableAndName.Length
                'sectionName = SectionTableAndName.Substring(pos + 1)
                '                   sectionName = "W8x10"
                section.SetName(sectionName, options)

                ' --------------------------------------------
                '    member
                ' --------------------------------------------
                member.SetPQPoints(com_startPoint, com_endPoint, options)
                member.SetSTFMaterial(material, options)
                member.SetSTFSection(section, options)


                '                    If pos < 0 Then pos = StructuralExpressionBuilderData.Length
                '                    familyName = StructuralExpressionBuilderData.Substring(0, pos)
                '                   partName = StructuralExpressionBuilderData.Substring(pos + 1)
                member.SetPartFamily(familyName)
                member.SetPartName(partName)

                member.SetPlacementPoint(placementPoint, options)

                member.CreateTFFormRecipeList(options)

                Dim formRecipeList As TFFormRecipeList = DirectCast(member.GetTFFormRecipeList(options), TFFormRecipeList)

                Dim formRecipe As TFFormRecipe = formRecipeList.AsTFFormRecipe

                formRecipe.Synchronize(options)

                'If Not GetElement() Is Nothing Then ' if we don't yet have an element, then the first time we do,
                '    '  we 'add' it to the file

                '    PersistMode = PersistOptions.RemoveAndAdd ' once we have an element, then in the case of Structural 'cells' we have
                '    ' to use this special 'RemoveAndAdd' method. Eventually we will
                'End If                                        ' work out why the 'normal' 'Replace' options does not work
                ' explicilty 'removing' the old cell and adding the new cell must
                ' bemore 'expensive' than a simple replace

                SetElement(formRecipe.GetElementForPersisting(options))

            End If
            'End If
            Return True

        End Function
        '       <Bentley.GenerativeComponents.Update(), Bentley.GenerativeComponents.Clone()> _

        <Update()> _
                Public Function ByLine(ByVal updateContext As FeatureUpdateContext, _
                                   <Replicatable(), ParentModel()> ByVal Line As ILine, _
                                   <SpecializedExpressionBuilder("PlaceStructuralExpressionBuilder")> ByVal StructuralExpressionBuilderData As String, _
                                   <Out()> ByRef Length As Double) As Boolean

            'DeleteAllSubFeatures(updateContext)

            'If updateContext.InDynamics Then
            '    'Dim comElement As Element = MSApp.CreateLineElement2(TemplateElement, com_startPoint, com_endPoint)
            '    'SetElement(comElement)
            '    'Length = comElement.AsLineElement().Length
            '    Return False
            'End If

            'DeleteElement(updateContext)

            Dim rotation As Double
            Length = 0.0
            If Not Line Is Nothing Then
                Dim com_startPoint As Point3d = DgnTools.ToPoint3d(Line.StartPoint.DPoint3d)
                Dim com_endPoint As Point3d = DgnTools.ToPoint3d(Line.EndPoint.DPoint3d)


                Dim sectionName As String = ""
                Dim familyName As String = ""
                Dim partName As String = ""

                Dim pos As Integer = StructuralExpressionBuilderData.IndexOf(":", 0)
                Dim pos2 As Integer
                pos2 = 0
                If pos > 0 Then
                    familyName = StructuralExpressionBuilderData.Substring(0, pos)
                    pos2 = pos + pos2
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    partName = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    sectionName = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    Dim rotationStr As String
                    rotationStr = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    rotation = Val(rotationStr)
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If
                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                Dim placementPoint As Integer
                If pos > 0 Then
                    Dim placementPointStr As String
                    Dim dPlacementPoint As Double
                    placementPointStr = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    dPlacementPoint = Val(placementPointStr)
                    placementPoint = CInt(dPlacementPoint)
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                Dim member As STFLinearMember
                Dim section As STFSection
                Dim material As STFMaterial
                Dim memberList As STFLinearMemberList
                Dim sectionList As STFSectionList
                Dim materialList As STFMaterialList

                memberList = New STFLinearMemberList
                sectionList = New STFSectionList
                materialList = New STFMaterialList

                member = DirectCast(memberList, STFLinearMember)
                section = DirectCast(sectionList, STFSection)
                material = DirectCast(materialList, STFMaterial)

                Dim options As String = String.Empty

                ' --------------------------------------------
                '    material
                ' --------------------------------------------
                material.SetName("Steel", options)
                material.SetGrade("A36", options)
                member.SetRotation(rotation)

                ' --------------------------------------------
                '    section
                ' --------------------------------------------

                '                    Dim pos As Integer = SectionTableAndName.IndexOf(":")
                '                    If pos < 0 Then pos = SectionTableAndName.Length
                'sectionName = SectionTableAndName.Substring(pos + 1)
                '                   sectionName = "W8x10"
                section.SetName(sectionName, options)

                ' --------------------------------------------
                '    member
                ' --------------------------------------------
                member.SetPQPoints(com_startPoint, com_endPoint, options)
                member.SetSTFMaterial(material, options)
                member.SetSTFSection(section, options)


                '                    If pos < 0 Then pos = StructuralExpressionBuilderData.Length
                '                    familyName = StructuralExpressionBuilderData.Substring(0, pos)
                '                   partName = StructuralExpressionBuilderData.Substring(pos + 1)
                member.SetPartFamily(familyName)
                member.SetPartName(partName)

                member.SetPlacementPoint(placementPoint, options)

                member.CreateTFFormRecipeList(options)

                Dim formRecipeList As TFFormRecipeList = DirectCast(member.GetTFFormRecipeList(options), TFFormRecipeList)

                Dim formRecipe As TFFormRecipe = formRecipeList.AsTFFormRecipe

                formRecipe.Synchronize(options)

                'If Not GetElement() Is Nothing Then

                '    PersistMode = PersistOptions.RemoveAndAdd

                'End If

                SetElement(formRecipe.GetElementForPersisting(options))


            End If
            Return True

        End Function

        <Update()> _
        Public Function ByCurve(ByVal updateContext As FeatureUpdateContext, _
                                   <Replicatable(), ParentModel()> ByVal Curve As ICurve, _
                                   <SpecializedExpressionBuilder("PlaceStructuralExpressionBuilder")> ByVal StructuralExpressionBuilderData As String, _
                                   <Out()> ByRef Length As Double) As Boolean

            'DeleteAllSubFeatures(updateContext)

            'If updateContext.InDynamics Then
            '    'Dim comElement As Element = MSApp.CreateLineElement2(TemplateElement, com_startPoint, com_endPoint)
            '    'SetElement(comElement)
            '    'Length = comElement.AsLineElement().Length
            '    Return False
            'End If

            'DeleteElement(updateContext)

            Dim rotation As Double
            Length = 0.0
            If Not Curve Is Nothing Then
                Dim com_startPoint As Point3d = DgnTools.ToPoint3d(Curve.StartPoint.DPoint3d)
                Dim com_endPoint As Point3d = DgnTools.ToPoint3d(Curve.EndPoint.DPoint3d)

                Dim sectionName As String = ""
                Dim familyName As String = ""
                Dim partName As String = ""
                Dim pathNode As New TFBrepList
                Dim oCurveEl As CurveElement = Nothing

                '                    oCurveEl = Curve.CurveElement
                '    General.AddElement oCurveEl
                '    oCurveEl.Redraw msdDrawingModeNormal
                pathNode.InitFromElement2(Curve.GetElement(), DgnTools.MSApp.ActiveModelReference)

                Dim brepType As TFdBrepType
                brepType = pathNode.AsTFBrep.GetType()
                If brepType <> TFdBrepType.tfdBrepTypeWire Then
                    'SendErrorReport("Only open curves are supported by this command")
                    Return False
                End If
                Dim pos As Integer = StructuralExpressionBuilderData.IndexOf(":", 0)
                Dim pos2 As Integer
                pos2 = 0
                If pos > 0 Then
                    familyName = StructuralExpressionBuilderData.Substring(0, pos)
                    pos2 = pos + pos2
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    partName = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    sectionName = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                If pos > 0 Then
                    Dim rotationStr As String
                    rotationStr = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    rotation = Val(rotationStr)
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If
                pos = StructuralExpressionBuilderData.IndexOf(":", pos2 + 1)
                Dim placementPoint As Integer
                If pos > 0 Then
                    Dim placementPointStr As String
                    Dim dPlacementPoint As Double
                    placementPointStr = StructuralExpressionBuilderData.Substring(pos2 + 1, (pos - pos2 - 1))
                    dPlacementPoint = Val(placementPointStr)
                    placementPoint = CInt(dPlacementPoint)
                    pos2 = (pos - pos2 - 1) + pos2 + 1
                End If

                Dim member As STFLinearMember
                Dim section As STFSection
                Dim material As STFMaterial
                Dim memberList As STFLinearMemberList
                Dim sectionList As STFSectionList
                Dim materialList As STFMaterialList

                memberList = New STFLinearMemberList
                sectionList = New STFSectionList
                materialList = New STFMaterialList

                member = DirectCast(memberList, STFLinearMember)
                section = DirectCast(sectionList, STFSection)
                material = DirectCast(materialList, STFMaterial)

                Dim options As String = String.Empty

                ' --------------------------------------------
                '    material
                ' --------------------------------------------
                material.SetName("Steel", options)
                material.SetGrade("A36", options)
                member.SetRotation(rotation)

                ' --------------------------------------------
                '    section
                ' --------------------------------------------

                '                    Dim pos As Integer = SectionTableAndName.IndexOf(":")
                '                    If pos < 0 Then pos = SectionTableAndName.Length
                'sectionName = SectionTableAndName.Substring(pos + 1)
                '                   sectionName = "W8x10"
                section.SetName(sectionName, options)

                ' --------------------------------------------
                '    member
                ' --------------------------------------------
                ' member.SetPQPoints(start, end, options)
                member.SetPath(pathNode)

                member.SetSTFMaterial(material, options)
                member.SetSTFSection(section, options)


                '                    If pos < 0 Then pos = StructuralExpressionBuilderData.Length
                '                    familyName = StructuralExpressionBuilderData.Substring(0, pos)
                '                   partName = StructuralExpressionBuilderData.Substring(pos + 1)
                member.SetPartFamily(familyName)
                member.SetPartName(partName)

                member.SetPlacementPoint(placementPoint, options)

                member.CreateTFFormRecipeList(options)

                Dim formRecipeList As TFFormRecipeList = DirectCast(member.GetTFFormRecipeList(options), TFFormRecipeList)

                Dim formRecipe As TFFormRecipe = formRecipeList.AsTFFormRecipe

                formRecipe.Synchronize(options)

                If Not GetElement() Is Nothing Then

                    PersistMode = PersistOptions.RemoveAndAdd

                End If

                SetElement(formRecipe.GetElementForPersisting(options))

            End If
            Return True

        End Function

    End Class

End Namespace
